/*
 * Copyright (c) 2006-2007 Israfil Consulting Services Corporation
 * Copyright (c) 2006-2007 Christian Edward Gruber
 * All Rights Reserved
 * 
 * This software is licensed under the Berkeley Standard Distribution license,
 * (BSD license), as defined below:
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this 
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of Israfil Consulting Services nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 * 
 * $Id: AbstractFlexMojo.java 570 2007-11-22 13:07:05Z christianedwardgruber $
 */
package net.israfil.mojo.flex2;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;


/**
 * Base class for flex2/actionscript3 plugin
 *
 * @author <a href="cgruber@israfil.net">Christian Edward Gruber</a>
 * @author <a href="tspurway@gmail.com">Tim Spurway</a>
 * @version $Id: AbstractFlexMojo.java 570 2007-11-22 13:07:05Z christianedwardgruber $
 */
public abstract class AbstractFlexCompilerMojo extends AbstractFlexMojo {
	
	private static final String SWF_SUFFIX = ".swf";
	private static final String[] FLEX_FRAMEWORKS = { "automation","framework","playerglobal","flex","utilities","rpc" };
	private static final String[] FLEX_OPTIONAL_FRAMEWORKS = { "charts", "automation_charts", "fds" };
	
	/**
	 * Resolve extra libraries (such as charts or fds) from 
	 * ${flex.home}/frameworks/libs.  Default is false, in which case 
	 * these (and other) swcs should be deployed as flex artifacts (swcs).
	 * 
	 * @parameter alias="resolve-extra-framework-libs" default="false"
	 */
	protected boolean resolveExtraSwcsFromFlexFrameworksLibs = false;

    /**
	 * The current locale.
	 * 
	 * @parameter expression="${flex.locale}" default="en_US"
	 */
	protected String locale = "en_US";

    /**
     * @parameter expression="${flex.compiler.optimize}" default="false"
     */
    protected boolean optimize;

    /**
     * @parameter expression="${flex.compiler.profile}" default="false"
     */
    protected boolean profile;

    /**
     * @parameter expression="${flex.compiler.strict}" default="false"
     */
    protected boolean strict;

    /**
     * @parameter expression="${flex.compiler.use-network}" default="false"
     */
    protected boolean useNetwork;
	
    /**
     * @parameter expression="${flex.compiler.show-warnings}" default="false"
     */
    protected boolean warnings;

    /**
     * @parameter expression="${flex.compiler.incremental}" default="false"
     */
    protected boolean incremental;

    /**
     * @parameter expression="${flex.compiler.show-actionscript-warnings}" default="false"
     */
    protected boolean showActionscriptWarnings;

    /**
     * @parameter expression="${flex.compiler.show-binding-warnings}" default="false"
     */
    protected boolean showBindingWarnings;

    /**
     * @parameter expression="${flex.compiler.show-deprecation-warnings}" default="false"
     */
    protected boolean showDeprecationWarnings;
	

    /**
     * @parameter expression="${flex.licenses}" 
     */
    protected License[] licenses;
	

    /**
     * @parameter expression="${flex.dataservices.config}" 
     */
    protected File dataServicesConfig;
      
	public AbstractFlexCompilerMojo() {
		super();
	}

	/**
     * Overload this to produce a test-jar, for example.
     */
    protected String getClassifier() {
    	return null;
    }

    protected File getOutputFile() {
    	return getFile(outputDirectory, finalName, classifier);
    }

    
    
     
    protected List prepareParameters() throws MojoFailureException, MojoExecutionException {
    	List parameters = super.prepareParameters();
   
		// define output file.
		File outFile = getOutputFile();
		parameters.add("-output");
		try {
			parameters.add(outFile.getCanonicalFile().getAbsolutePath());
		} catch (IOException e) {
			throw new MojoExecutionException("Exception attempting to set output file: " + outFile, e);
		}		

		// add in locale
		parameters.add("-compiler.locale");
		parameters.add(locale);
		
		// add in license
		
		getLog().info("Attaching licenses.");
		for (int i = 0; licenses != null && i < licenses.length; i++) {
			getLog().debug("Adding license: " + licenses[i].getProduct() + "=" + licenses[i].getSerialNumber());
			parameters.add("-licenses.license");
			parameters.add(licenses[i].getProduct());
			parameters.add(licenses[i].getSerialNumber());
		}


		// add in binary options.
		if (optimize) parameters.add("-compiler.optimize");
		if (profile) parameters.add("-compiler.profile");
		if (strict) parameters.add("-compiler.strict");
		if (useNetwork) parameters.add("-use-network");
		if (warnings) parameters.add("-warnings");
		if (incremental) parameters.add("-compiler.incremental");
		if (showActionscriptWarnings) parameters.add("-show-actionscript-warnings");
		if (showBindingWarnings) parameters.add("-show-binding-warnings");
		if (showDeprecationWarnings) parameters.add("-show-deprecation-warnings");
		//verbose-stacktraces

		
		if (dataServicesConfig != null) {
			parameters.add("-compiler.services");
			try {
				parameters.add(dataServicesConfig.getCanonicalFile().getAbsolutePath());
			} catch (IOException e) {
				throw new MojoExecutionException("Unable to set data services config file.", e);
			}			
		}
		
		
		// Add in dependency .swfs.
		Set linkedLibraryPaths = new HashSet();
		Set artifacts = project.getArtifacts();
		getLog().debug("Dependency artifacts: " + artifacts);
		Iterator depsIterator = artifacts.iterator();
		while (depsIterator.hasNext()) {
			Artifact dep = (Artifact)depsIterator.next();
	        // TODO: let the scope handler deal with this
	        if ( Artifact.SCOPE_COMPILE.equals( dep.getScope() ) || 
				        	Artifact.SCOPE_PROVIDED.equals( dep.getScope() ) ||
				            Artifact.SCOPE_SYSTEM.equals( dep.getScope() ) ) {
				if ("swc".equals(dep.getType())) {
					getLog().debug("Linking dependency: " + dep);
					try {
						String absPath = dep.getFile().getCanonicalFile().getAbsolutePath();
						linkedLibraryPaths.add(absPath);
						//includedLibraryPaths.add(absPath);
					} catch (IOException e) {
						throw new MojoExecutionException("Dependency file not present or readable: " + dep.getFile().getAbsolutePath(),e);
					}
				} else if ("swf".equals(dep.getType())) {
					throw new MojoExecutionException("Cannot link swf project '" + 
						dep + "' into other swf.  Compile dependencies must be .swcs.");
				}
	        } else {
	        	getLog().debug("Skipping non-compile artifact: " + dep);
	        }
	        
		}
		
		//	FIXME: What do we do with include-libraries???
		//	add included library paths.
		//	Set includedLibraryPaths = new HashSet();
		//	Iterator inclLibsIter = includedLibraryPaths.iterator();
		//	while (inclLibsIter.hasNext()) 
		//		parameters.add("-include-libraries+=" + inclLibsIter.next());

		// add linked library paths.
		Iterator linkedLibsIter = linkedLibraryPaths.iterator();
		while (linkedLibsIter.hasNext()) 
			parameters.add("-library-path+=" + linkedLibsIter.next());
		

    	return parameters;
    }


}
